package com.iceGame;

import java.util.ArrayList;
import java.util.List;

import com.badlogic.gdx.math.Rectangle;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.physics.box2d.Body;
import com.badlogic.gdx.physics.box2d.BodyDef;
import com.badlogic.gdx.physics.box2d.MassData;
import com.badlogic.gdx.physics.box2d.PolygonShape;
import com.badlogic.gdx.physics.box2d.World;
import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
/**
 * The class can be used to create objects that move on a pre-defined path.
 * @author amit
 *
 */
public abstract class MovingGameObject {
	
	final int LOOP = 1;
	final int NONE = 0;
	final int REVERSE = 2;
	
	final int STOP = 0;
	final int PAUSING = 1;
	final int MOVING = 2;
	final int REVERSING = 3;
	
	final float deltaDistance = 0.01f;
	public Body body;
	public int behavior;
	public int state;
	public List<Location> wayPoints;
	//public Vector2 position;
	public Vector2 heading;
	public float velocity;
	public PhysicsWorld world;
	private float lastDistance;
	private float timer;
	public int currentWPIndex;
	private boolean reverse;
	public float width;
	public float height;
	private Rectangle bounds;
	public MovingGameObject(PhysicsWorld world){
		this.world = world;
		timer = 0;
		currentWPIndex = 0;
		reverse = false;
		heading = new Vector2(0,0);
		state = PAUSING;
		behavior = LOOP;
		lastDistance = 0;
		this.wayPoints = new ArrayList<Location>();
	}
	public MovingGameObject(PhysicsWorld world,float x, float y, float width, float height){
		//position = new Vector2(x,y);
		this(world);
		this.width = width;
		this.height = height;
		setBody(world.world,x,y,width,height);
		bounds = new Rectangle(x,y,width,height);
		this.wayPoints.add(new Location(x, y, 0));
	}
	public MovingGameObject(PhysicsWorld world,Body body){
		this(world);
		//position = new Vector2(body.getPosition().x,body.getPosition().y);
		this.body = body;

	}
	
	protected abstract void setBody(World world, float x, float y, float width,float height);
	/*
	private void setBody(World world, float x, float y, float width,float height) {
		BodyDef bodydef = new BodyDef();
		bodydef.position.set(x,y);
		bodydef.type = BodyType.KinematicBody;
		body = world.createBody(bodydef);
		PolygonShape shape = new PolygonShape();
		shape.setAsBox(width/2, height/2);
		body.createFixture(shape, 0);
		MassData data = new MassData();
		data.mass = 0;
		data.I = 0;
		body.setMassData(data);
		
	}
	*/
	/**
	 * adds a new way point to the route
	 * @param wayPoint
	 */
	public void addWayPoint(Location wayPoint){
		wayPoints.add(wayPoint);
	}
	public void update(float deltaTime) {
		switch (state){
		case PAUSING:
			updatePausing(deltaTime);
			break;
		case MOVING:
			updateMoving(deltaTime);
			break;
		case STOP:
			//don't do shit
			
		}

	}
	private void updateMoving(float deltaTime) {
		timer+= deltaTime;
		Location next = this.wayPoints.get(currentWPIndex);
		float distance = next.position.dst(body.getPosition());
		if (distance <= deltaDistance || (distance > lastDistance && lastDistance != 0)){
			body.getPosition().set(next.position);
			state = PAUSING;
			body.setLinearVelocity(heading.set(0, 0));
			lastDistance = 0;
		}
		else{
			body.getPosition().add(heading.nor().mul(velocity * timer));
			lastDistance = distance;
		}
		timer = 0;
		
	}
	public void updatePausing(float deltaTime){
		timer+= deltaTime;
		float wpDelay = wayPoints.get(currentWPIndex).waitTime;
		if (timer >= wpDelay){
			if (reverse){
				currentWPIndex--;
			}
			else{
				currentWPIndex++;
			}
			if (currentWPIndex >= wayPoints.size()){
				if (behavior == LOOP){
					currentWPIndex = 0;
				}
				else if (behavior == REVERSE){
					reverse = true;
					currentWPIndex-= 2;
				}
				state = MOVING;
			}
			else if (currentWPIndex < 0){
				reverse = false;
				currentWPIndex +=2;
			}		
			state = MOVING;
			timer -= wpDelay;
			Vector2 nextWP = wayPoints.get(currentWPIndex).position.cpy();
			heading.set(nextWP.sub(body.getPosition()));
			body.setLinearVelocity(heading.nor().mul(velocity));
		}
	}
	public void setWaypints(ArrayList<Location> waypoints) {
		this.wayPoints = waypoints;
		
	}
	public Rectangle getBounds(){
		bounds.x = body.getPosition().x;
		bounds.y = body.getPosition().y;
		return bounds;
	}
}
